package cate.game.activity.godequip;

import cate.common.table.activity.godequip.row.GodEquipBaseRow;
import cate.common.table.activity.godequip.row.GodEquipPoolRow;
import cate.common.table.activity.godequip.row.GodEquipScoreRow;
import cate.common.table.d.GDCrossRank;
import cate.common.table.d.GDFunc;
import cate.common.table.d.GDOperation;
import cate.common.table.item.equip.row.EquipBaseRow;
import cate.common.util.GameResult;
import cate.common.util.random.RWList;
import cate.game.activity.LogDetail;
import cate.game.activity.base.core.RoleActivitySingle;
import cate.game.activity.crossrank.po.CrossRankActivity;
import cate.game.activity.godequip.msg.GodEquipActivityInfoResp;
import cate.game.chat.ChatContentParam;
import cate.game.res.MixRes;
import cate.game.res.MixResItem;
import cate.game.role.Role;
import easy.java.dev.note.NoteField;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

public class GodEquipActivity extends RoleActivitySingle {
    @NoteField("已抽奖次数,用于触发指定保底")
    public int drawTimes;
    @NoteField("幸运值")
    public int luckyScore;
    @NoteField("历史抽取次数，抽中大奖重置")
    public long historyTimes;
    @NoteField("寻宝幸运值奖励领取记录")
    public List<Integer> takeList;

    public static final int GOOD = 1;
    public static final int BAD = 0;

    @Override
    public void initialize(Role role) {
        super.initialize(role);
        if (takeList == null) {
            takeList = new ArrayList<>();
        }
    }

    @Override
    public void onRoleOpen() {

    }

    @Override
    public void onRoleEnd() {
        this.drawTimes = 0;
        this.luckyScore = 0;
        this.historyTimes = 0;
        this.takeList.clear();
    }

    @Override
    public void initSend() {
        noticeUpdate();
    }

    @Override
    public void excelCheck() {

    }

    public void noticeUpdate() {
        role.sendNow(new GodEquipActivityInfoResp(this));
    }

    public GameResult<GodEquipActivity> singleDraw() {
        GameResult<GodEquipActivity> r = new GameResult<>();
        r.data = this;
        GodEquipBaseRow baseRow = findBaseRow();
        if (baseRow == null) {
            return r.fail("活动配置不存在");
        }
        if (StringUtils.isBlank(baseRow.onceCost)) {
            return r.fail("单抽消耗未配置");
        }
        MixRes cost = new MixRes(baseRow.onceCost);
        GameResult<MixResItem> consume = cost.consume(role);
        if (!consume.ok()) {
            role.getGame().notice.tipResItem(role, consume.data);
            return r.fail(consume);
        }
        r = draw(1);
        return r;
    }

    public GameResult<GodEquipActivity> tenDraw() {
        GameResult<GodEquipActivity> r = new GameResult<>();
        r.data = this;
        GodEquipBaseRow baseRow = findBaseRow();
        if (baseRow == null) {
            return r.fail("活动配置不存在");
        }
        if (StringUtils.isBlank(baseRow.tenCost)) {
            return r.fail("十抽消耗未配置");
        }
        MixRes cost = new MixRes(baseRow.tenCost);
        GameResult<MixResItem> consume = cost.consume(role);
        if (!consume.ok()) {
            role.getGame().notice.tipResItem(role, consume.data);
            return r.fail(consume);
        }
        r = draw(10);
        return r;
    }


    public GameResult<GodEquipActivity> draw(int times) {
        GameResult<GodEquipActivity> r = new GameResult<>();
        r.data = this;
//        开始抽卡
        MixRes draw = drawExe(times);
        if (draw.isEmpty()) {
            return r.fail("奖励未配置");
        }
        CrossRankActivity crossRankActivity = role.getActivity().getEnableActivitySingle(GDFunc.Help.CROSS_GOD_EQUIP_RANK);
        if (crossRankActivity != null) {
            for (int i = 0; i < times; ++ i) {
                if (Math.random() <= 0.15) {
                    draw.addList(new MixRes(GDCrossRank.GOD_EQUIP_RANK_EXTRA_REWARD));
                }
            }
        }
        draw.addAndDialog(role, true, GDOperation.GOD_EQUIP);
        role.getHistory().action.godEquipDrawTimes(times);
        return r;
    }

    public GameResult<GodEquipActivity> takeCallReward(int tid) {
        GameResult<GodEquipActivity> r = new GameResult<>();
        r.data = this;
        GodEquipBaseRow baseRow = findBaseRow();
        if (baseRow == null) {
            return r.fail("活动配置不存在");
        }
        List<GodEquipScoreRow> rewardRows = fingScoreRowsByGroup(baseRow.group);
        if (rewardRows.isEmpty()) {
            return r.fail("活动不存在累计奖励");
        }
        GodEquipScoreRow row = fingScoreRow(tid);
        if (row == null) {
            return r.fail("找不到对应的奖励配置");
        }
        if (row.group != baseRow.group) {
            return r.fail("非本期奖励，不可领取");
        }
        if (this.luckyScore < row.luckyLimit) {
            return r.fail("未达成领奖条件");
        }
        if (this.takeList.contains(tid)) {
            return r.fail("奖励已领取");
        }
        MixRes reward = new MixRes(row.reward);
        reward.addAndDialog(role, true, GDOperation.GOD_EQUIP, tid);
        takeList.add(tid);
        refresh();
        return r;
    }

    private void refresh() {
        int group = findBaseRow().group;
        List<Integer> ids = role.getGame().table.godEquip.score.getRowsByGroup(group).stream().map(row -> row.id).collect(Collectors.toList());
        if (takeList.containsAll(ids)) {
            int max = role.getGame().table.godEquip.score.getMaxTimesByGroup(group);
            if (max == 0) {
                return;
            }
            luckyScore -= max;
            takeList.clear();
        }
    }

    private MixRes drawExe(int times) {
        MixRes res = new MixRes();
        GodEquipBaseRow baseRow = findBaseRow();
        if (baseRow == null) {
            return res;
        }
        int rareNum = 0;
        for (int i = 0; i < times; i++) {
            this.historyTimes++;
            if (historyTimes > baseRow.cheatLimit) {
                drawTimes++;
            }
            GodEquipPoolRow item = drawItem(rareNum);
            if (item == null) {
                return res;
            }
            MixRes rewardItem = new MixRes(item.reward);
            if (Objects.requireNonNull(findPoolRow(item.id)).isRare == 1) {
                rareNum++;
            }
            if (Objects.requireNonNull(findPoolRow(item.id)).sendLamp == 1) {
                lamp(item.id);
            }
            if (Objects.requireNonNull(findPoolRow(item.id)).ifRecord == 1) {
                GodEquipActivityHandler handler = role.getGame().activityGlobal.getEnableHandler(funcId());
                handler.addLog(baseRow, activityId(), new LogDetail(role.getGame().config.srvId, role.getBase().name, rewardItem));
            }
            EquipBaseRow equipBaseRow = role.getGame().table.equip.base.get(rewardItem.items.get(0).tid);
            role.getHistory().action.godEquipQuality(equipBaseRow.quality);
            res.addList(rewardItem);
        }
        MixRes base = new MixRes(baseRow.score).multiply(times);
        res.addList(base);
        this.luckyScore += times * baseRow.luckyValue;
//        this.historyTimes += times;
        return res;
    }


    private void lamp(int id) {
        GodEquipPoolRow row = findPoolRow(id);
        if (row.sendLamp != 0) {
            List<ChatContentParam> params = new ArrayList<>();
            params.add(ChatContentParam.c(role.getBase().name));
            params.add(ChatContentParam.c(ChatContentParam.TYPE_MIX_RES, new MixRes(row.reward)));
            role.getGame().notice.lampOnline(role, row.contentId, params);
        }
    }

    private GodEquipPoolRow drawItem(int rareNum) {
        GodEquipBaseRow baseRow = findBaseRow();
        if (baseRow == null) {
            return null;
        }
        RWList<GodEquipPoolRow> pool;
        if (historyTimes <= baseRow.cheatLimit) {
            //前n次只出垃圾
            pool = createCheatPool(BAD, baseRow.group);
            pool.setup();
        } else {
            //如果脸白
            if (rareNum >= baseRow.luckyLimit) {
                pool = createCheatPool(BAD, baseRow.group);
            } else if (drawTimes >= baseRow.unluckyLimit) {
                //如果脸黑
                pool = createCheatPool(GOOD, baseRow.group);
            } else {
                pool = createNormalPool(baseRow.group);
            }
        }
        if (pool.isEmpty()) {
            return null;
        }
        GodEquipPoolRow item = pool.get();
        if (historyTimes > baseRow.cheatLimit) {
            if (item.isRare == 1) {
                drawTimes = 0;
                historyTimes = 0;
            }
        }
        return item;
    }

    private GodEquipBaseRow findBaseRow() {
        return role.getGame().table.godEquip.base.getRowByDay(role.getGame().status.getOpenDay());
    }

    private RWList<GodEquipPoolRow> createCheatPool(int cheatState, int group) {
        RWList<GodEquipPoolRow> pool = new RWList<>();
        List<GodEquipPoolRow> rows = findCheatRows(cheatState, group);
        pool.addAndSetup(rows);
        return pool;
    }

    private RWList<GodEquipPoolRow> createNormalPool(int group) {
        RWList<GodEquipPoolRow> pool = new RWList<>();
        List<GodEquipPoolRow> rows = findPoolRowsByGroup(group);
        pool.addAndSetup(rows);
        return pool;
    }

    private GodEquipPoolRow findPoolRow(int tid) {
        return role.getGame().table.godEquip.pool.get(tid);
    }

    private List<GodEquipPoolRow> findPoolRowsByGroup(int groupId) {
        return role.getGame().table.godEquip.pool.groupMap.get(groupId);
    }

    private List<GodEquipPoolRow> findCheatRows(int cheatState, int groupId) {
        List<GodEquipPoolRow> rows = findPoolRowsByGroup(groupId);
        return rows.stream().filter(row -> row.isRare == cheatState).collect(Collectors.toList());
    }

    private List<GodEquipScoreRow> fingScoreRowsByGroup(int group) {
        return role.getGame().table.godEquip.score.getRowsByGroup(group);
    }

    private GodEquipScoreRow fingScoreRow(int tid) {
        return role.getGame().table.godEquip.score.get(tid);
    }

    public void GMAddDrawTimes(int add) {
        this.drawTimes = add;
        this.historyTimes = add;
    }

}
